package com.espirit.weixin.core;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.espirit.weixin.message.MessageUtil;
import com.espirit.weixin.message.TextMessage;
import com.googlecode.cswish.test.mock.struts2.jsp.StrutsMockHttpServletRequest;
import com.googlecode.cswish.test.mock.struts2.jsp.StrutsMockHttpServletResponse;
import com.googlecode.cswish.util.FrameConstant;

public class WeiXinFilter implements Filter {
	
	private static final Log logger = LogFactory.getLog(SignUtil.class);
	
	@Override
	public void init(FilterConfig filterConfig) throws ServletException {

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		request.setCharacterEncoding("UTF-8");
		response.setCharacterEncoding("UTF-8");

		HttpServletRequest httpRequest = (HttpServletRequest) request;
		String requestMethod = httpRequest.getMethod();
		if ("GET".equals(requestMethod)) {
			doGet(httpRequest, response, chain);
		} else if ("POST".equals(requestMethod)) {
			doPost(httpRequest, response, chain);
		}
	}

	private void doGet(HttpServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		String uri = request.getRequestURI();
		String contextPath = request.getContextPath();
		int wxIndex = uri.indexOf(".wx");
		String servletPath = uri.substring(contextPath.length(), wxIndex) + ".html";

		StrutsMockHttpServletRequest req = new WeiXinStrutsMockHttpServletRequest();
		req.setupGetContentType("text/html");
		Map<String, String[]> parameter = new HashMap<>();
		Enumeration<?> paramNames = request.getParameterNames();
		while (paramNames.hasMoreElements()) {
			String paramName = String.valueOf(paramNames.nextElement());
			String[] values = request.getParameterValues(paramName);
			parameter.put(paramName, values);
		}
		
		parameter.put(FrameConstant.PARAM_RESULTCODE, new String[] { FrameConstant.PARAM_RESULT_STRING });
		req.setParameterMap(parameter);
		req.setRequestURI(contextPath + servletPath);
		req.setupGetServletPath(servletPath);
		req.setupGetContext(request.getContextPath());
		StringWriter writer = new StringWriter();
		StrutsMockHttpServletResponse resp = new StrutsMockHttpServletResponse();
		resp.setWriter(new PrintWriter(writer));
		chain.doFilter(req, resp);

		String result = writer.toString();
		PrintWriter out = response.getWriter();
		if (StringUtils.isNotBlank(result)) {
			out.print(result);
		}
		out.flush();
		out.close();
	}

	private void doPost(HttpServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		String uri = request.getRequestURI();
		String contextPath = request.getContextPath();
		int wxIndex = uri.indexOf(".wx");
		String servletPath = uri.substring(contextPath.length(), wxIndex) + ".html";
		
		String respMessage = null;
		// 默认返回的文本消息内容
		String respContent = "请求处理异常，请稍候尝试！";
		TextMessage textMessage = null;

		String xml = IOUtils.toString(request.getInputStream());
		//String xml = request.getParameter("xmlData");
		if (logger.isDebugEnabled()) {
			logger.debug("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
			logger.debug("requestMessage:\n" + xml);
			logger.debug("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
		}
		
		// xml请求解析
		Map<String, String> properties = MessageUtil.parseXml(xml);

		// 发送方帐号（open_id）
		String fromUserName = properties.get("fromUserName");
		// 公众帐号
		String toUserName = properties.get("toUserName");
		// 消息类型
		String msgType = properties.get("msgType");
		
		try {
			StrutsMockHttpServletRequest req = new WeiXinStrutsMockHttpServletRequest();
			req.setupGetContentType("text/html");
			req.setupGetMethod("POST");
			Map<String, String[]> parameter = new HashMap<>();
			for (Entry<String, String> entry : properties.entrySet()) {
				parameter.put("message." + entry.getKey(), new String[] { entry.getValue() });

			}
			parameter.put(FrameConstant.PARAM_GENERIC_TYPE, new String[] { MessageUtil.getMessageClassName(msgType) });
			parameter.put(FrameConstant.PARAM_RESULTCODE, new String[] { FrameConstant.PARAM_RESULT_JSON });
			req.setParameterMap(parameter);
			req.setRequestURI(contextPath + servletPath);
			req.setupGetServletPath(servletPath);
			req.setupGetContext(request.getContextPath());
			StringWriter writer = new StringWriter();
			StrutsMockHttpServletResponse resp = new StrutsMockHttpServletResponse();
			resp.setWriter(new PrintWriter(writer));
			
			// build session
			
			// check permission
			// ...
			
			chain.doFilter(req, resp);

			respMessage = writer.toString();
		} catch (Exception e) {
			logger.error(e.getMessage(),e);
			textMessage = new TextMessage();
			textMessage.setToUserName(fromUserName);
			textMessage.setFromUserName(toUserName);
			textMessage.setCreateTime(new Date().getTime());
			textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
			textMessage.setFuncFlag(0);
			textMessage.setContent(respContent);
			respMessage = MessageUtil.textMessageToXml(textMessage);
		}
		if (logger.isDebugEnabled()) {
			logger.debug("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
			logger.debug("responseMessage:\n" + respMessage);
			logger.debug("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~");
		}
		PrintWriter out = response.getWriter();
		out.print(respMessage);
		out.flush();
		out.close();
	}

	@Override
	public void destroy() {

	}

	class WeiXinStrutsMockHttpServletRequest extends StrutsMockHttpServletRequest {
		
		public Enumeration<?> getHeaders(String name) {
			return Collections.emptyEnumeration();
		}

		public String getHeader(String name) {
			return null;
		}
	}

}
